package dm.ast.model.gen;

import dm.ast.*;
import test.utility.Randomly;

/**
 * 根据模板AST生成HAVING子句
 */
public class HavingGen extends ASTGenBase{
    @Override
    public DmASTNode gen(int astLevel, int wid_t, int dep_t) {
        /**
         * 为了减少-4028 | 无效的HVAING项错误
         * 此处对having子句的生成做了规定
         * 1、仅包含1个bool表达式
         * 2、bool表达式可以包含1个子查询
         * 3、bool表达式的左右表达式必须至少一个为集函数
         */
        DmHaving dmHaving = new DmHaving();
        dmHaving.setTargetWidt(wid_t);
        dmHaving.setTargetDept(dep_t);
        dmHaving.setASTLevel(astLevel);

        DmBoolExpression logicBoolExp = new DmBoolExpression();
        logicBoolExp.setTargetWidt(wid_t);
        logicBoolExp.setTargetDept(dep_t);
        logicBoolExp.setASTLevel(astLevel);
        DmDataType rType = Randomly.fromList(ExpressionGen.supportedExpRetType());
        DmOperator op = OperatorGen.logicOperatorRandom();
        logicBoolExp.setOperator(op);

        if(dep_t > 1){  //包含子查询，那么仅包含1个子查询，另外一个表达式由集函数填充
            ExpressionGen expGen = new ExpressionGen();
            expGen.setTestFlags(testFlags);
            DmExpression exp = (DmExpression)expGen.gen(astLevel , wid_t , dep_t , rType);
            logicBoolExp.setLeftExp(exp);
            DmColumn col1 = new DmColumn();
            col1.reType = rType;
            logicBoolExp.setRightExp(AggregateGen.getRandAggregate(rType , col1));
        }else { // 不包含子查询，那么可能2个都是由集函数填充，也可能由1个集函数，一个常量填充
            DmColumn col2 = new DmColumn();
            col2.reType = rType;
            DmExpression exp1 = AggregateGen.getRandAggregate(rType , col2);
            logicBoolExp.setLeftExp(exp1);
            DmExpression exp2 = null;
            int i = (int)Randomly.getNotCachedInteger(1 ,100);
            if(i < 80){
                exp2 = DmConstantGen.gen(rType);
                exp2.reType = rType;
            }else {
                DmColumn col3 = new DmColumn();
                col2.reType = rType;
                exp2 = AggregateGen.getRandAggregate(rType , col3);
            }
            logicBoolExp.setRightExp(exp2);
        }
        if(Randomly.getBoolean()){
            logicBoolExp.changeLeftRight();
        }
        dmHaving.havingCondition = logicBoolExp;

        return dmHaving;
    }
}
